/*
 * LDIR
 * 
 * LDIR, a GPS cartography application built for Let's Do It Romania eco 
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 * 
 * http://generasoftware.com/
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#ifndef IMAGEUTILS_H
#define IMAGEUTILS_H

// INCLUDES
#include <e32std.h>
#include <e32base.h>
#include <badesca.h>
#include <f32file.h>
#include <e32math.h>


#include <fbs.h>
#include <imageconversion.h>

class CGulIcon;
class CSprite;

// CONSTANTS
const TInt KImagesExtensionsCount = 5;
const TLitC<KImagesExtensionsCount> ImagesExtensions[] =
{
    {4, L".JPG"},
    {4, L".BMP"},
    {4, L".PNG"},
    {4, L".GIF"},
    {4, L".MBM"},
    {5, L".JPEG"}
};

// FORWARD DECLARATIONS
class CFbsBitmap;

// CLASS DECLARATION

/**
*  ImageUtils
*
*/
class ImageUtils
{
public: // Constructors and destructor
    /**
    * Loads an image from a given file.
    * @param aFilename
    */
    static CFbsBitmap* LoadImageL(const TDesC& aFilename, const TSize* aDesiredSize = NULL);

    /**
    * Saves an image to a given file.
    * @param aBitmap The bitmap to save.
    * @param aFilepath The path where to save the file.
    * @return KErrNone if save was successful, other system wide error codes otherwise.
    */
    static TInt SaveImageL(CFbsBitmap& aBitmap, const TDesC& aFilename, const TDesC8* aMimeType = NULL);
    /**
     * Copies one bitmap to another. Creates the destination bitmap.
     * @param aSource The source bitmap.
     * @param aDestination The destination bitmap.
     * @return KErrNone if successful, other system wide error codes otherwise.
     */
    static TInt CopyBitmapL(CFbsBitmap* aSource, CFbsBitmap*& aDestination);
    /**
     * Gets the available images
     */
    static CDesCArray* GetAvailableImagesLC(const TDesC& aDirPath);

    static CGulIcon* CreateIconL(const TDesC& aBitmapFile, TInt aBitmapId, TInt aMaskId, const TSize& aSize);

protected:
    /**
     * Browse a folder for files and subfolders. Stores found folders and files in
     * the two arrays.
     */
    static void BrowseForFilesL(CDesCArray* aDirList, CDesCArray* aFilesList, RFs& aFsSession);
    /**
    * Tests if a given filename matches an image extension.
    */
    static TBool MatchesExtension(TFileName& aFilename);
};

enum TImageOperations
{
    EImgOpNone,
    EImgOpLoad,
    EImgOpScale,
    EImgOpRotate,
    EImgOpConvert
};
// =============================================================================
// =============================================================================

/**
* Listener interface that can be used to listen for image loading operation
* completion events from CImageHandler.
*
* The class is intended to be implemented by a client class that observes the
* loading operation of image handler. The methods in this class
* are called by the image handler (class CImageHandler) when it loads
* an image.
*
* Reference to implementations of this listener interface can be passed as
* a parameter to the constructor of the image handler (class CImageHandler).
*/
class MImageHandlerCallback
{
public: // New functions
    /**
    * Called by CImageHandler when an image has been loaded.
    * @param aError Error code given by the CImageHandler or 0 (zero) if the image was loaded successfully.
    */
    virtual void ImageOperationCompleteL(const TInt aOperation, const TInt aError) = 0;
};

// =============================================================================
// =============================================================================
/**
*  CImageHandler
*  Image loader class.
*/

class CBitmapRotator;
class CBitmapScaler;

class CImageHandler : public CActive
{
public: // Constructors and destructor
    /** Factory method that constructs a CImageHandler by using the NewLC method and then cleans the cleanup stack. */
    static CImageHandler* NewL(RFs& aFs, MImageHandlerCallback* aCallback, CFbsBitmap* aBitmap, CFbsBitmap* aBitmapMask = NULL);
    /** Factory method that constructs a CImageHandler and leaves it to the cleanup stack. */
    static CImageHandler* NewLC(RFs& aFs, MImageHandlerCallback* aCallback, CFbsBitmap* aBitmap, CFbsBitmap* aBitmapMask = NULL);
    /** Desctructor. Destroys the CImageDecoder used by the image handler. */
    virtual ~CImageHandler();

public: // New functions
    /**
    * Sets the target bitmap where the bitmap data is loaded to.
    * @param aBitmap Bitmap where the image data is loaded to.
    * @param aBitmapMask Bitmap where the alpha channel data is loaded to.
    * @return True if operation is successfull, false if not.
    */
    TBool SetBitmapL( CFbsBitmap *aBitmap, CFbsBitmap *aBitmapMask = NULL);

    /**
    * Loads the given frame from the given file asynchronously.
    * @param aFileName Filename wherefrom the bitmap data is loaded.
    * @param aSync Specifies whether the operation is synchronously or asynchronously.
    * @param aSelectedFrame A single frame index in a multi-frame file. If not given the first frame is loaded.
    */
    void LoadFileL(const TFileName& aFileName, TSize* aDesiredSize = NULL, TInt aSelectedFrame = 0);

    /**
    * Loads the given image frame from the given descriptor asynchronously.
    * @param aData The descriptor wherefrom the bitmap data is loaded.
    * @param aSync Specifies whether the operation is synchronously or asynchronously.
    * @param aSelectedFrame A single frame index in a multi-frame file. If not given the first frame is loaded.
    */
    void LoadDesL(const TDesC8& aData, TSize* aDesiredSize = NULL, TInt aSelectedFrame = 0);

    /**
    * Returns the current frame information.
    * @return Current frame information.
    */
    const TFrameInfo& FrameInfo() const;

    void ScaleL(const TSize& aSize, TBool aKeepAspectRatio = ETrue);

private: // Functions from base classes

    /**
    * CActive::RunL() implementation. Called on image load success/failure.
    */
    void RunL();
    /**
    * CActive::Cancel() implementation. Stops decoding.
    */
    void DoCancel();

protected:
    /**
    * C++ default constructor. Just stores the given parameters to corresponding attributes.
    * @param aBitmap Bitmap where the image data is loaded to.
    * @param aFs File server reference that is used to load the image data.
    * @param aCallback Listener interface implementation that is notified when an image has been loaded.
    */
    CImageHandler(RFs &aFs, MImageHandlerCallback* aCallback, CFbsBitmap *aBitmap, CFbsBitmap *aBitmapMask);

    /**
    * 2nd phase constructor. Adds this object to the active scheduler.
    */
    void ConstructL();


    TSize LoadingImageSize(const TSize& aActualSize, const TSize& aDesiredSize);

private: // Data

    /** Image decoder that is used to load the image data from file. */
    CImageDecoder* iDecoder;
    CBitmapScaler* iScaler;
    CBitmapRotator* iRotator;
    /** Listener that is notified when an image has been loaded. */
    MImageHandlerCallback* iCallback;
    /** Bitmap (owned by the user of this class) where the loaded image data is put. */
    CFbsBitmap *iBitmap;
    /** Bitmap mask (owned by the user of this class) where the loaded alpha channel data is put. */
    CFbsBitmap *iBitmapMask;
    /** File server (owned by the user of this class) that is used to load the raw image data from files. */
    RFs& iFs;
    /** Current image frame information. */
    TFrameInfo iFrameInfo;
    TImageOperations iCurrentOperation;
    TBool iPendingMaskOperation;
    TBool iKeepAspectRatio;
    TSize iScaleSize;
};

#endif // IMAGEUTILS_H
